#include <unistd.h>
#include <pthread.h>
#include <errno.h>

pthread_cond_t wait_th1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t wait_th2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t wait_th3 = PTHREAD_COND_INITIALIZER;
pthread_cond_t wait_th4 = PTHREAD_COND_INITIALIZER;

pthread_mutex_t mtx1 = PTHREAD_MUTEX_INITIALIZER;;
pthread_mutex_t mtx2 = PTHREAD_MUTEX_INITIALIZER;;
pthread_mutex_t mtx3 = PTHREAD_MUTEX_INITIALIZER;;
pthread_mutex_t mtx4 = PTHREAD_MUTEX_INITIALIZER;;

int finished1 = 0;
int finished2 = 0;
int finished3 = 0;
int finished4 = 0;

void* th1(void *arg) {
	while(1) {
		pthread_mutex_lock(&mtx4);
		while(!finished4) {
			pthread_cond_wait(&wait_th4, &mtx4);
		}
		finished4 = 0;
		pthread_mutex_unlock(&mtx4);

		write(STDOUT_FILENO, "A", 1);

		pthread_mutex_lock(&mtx1);
		finished1 = 1;
		pthread_mutex_unlock(&mtx1);

		pthread_cond_signal(&wait_th1);
		sleep(1);
	}
}


void* th2(void *arg) {
	while(1) {
		pthread_mutex_lock(&mtx1);
		while(!finished1) {
			pthread_cond_wait(&wait_th1, &mtx1);
		}
		finished1 = 0;
		pthread_mutex_unlock(&mtx1);

		write(STDOUT_FILENO, "B", 1);

		pthread_mutex_lock(&mtx2);
		finished2 = 1;
		pthread_mutex_unlock(&mtx2);

		pthread_cond_signal(&wait_th2);
		sleep(1);
	}
}

void* th3(void *arg) {
	while(1) {
		pthread_mutex_lock(&mtx2);
		while(!finished2) {
			pthread_cond_wait(&wait_th2, &mtx2);
		}
		finished2 = 0;
		pthread_mutex_unlock(&mtx2);

		write(STDOUT_FILENO, "C", 1);

		pthread_mutex_lock(&mtx3);
		finished3 = 1;
		pthread_mutex_unlock(&mtx3);

		pthread_cond_signal(&wait_th3);
		sleep(1);
	}
}

void* th4(void *arg) {
	while(1) {
		pthread_mutex_lock(&mtx3);
		while(!finished3) {
			pthread_cond_wait(&wait_th3, &mtx3);
		}
		finished3 = 0;
		pthread_mutex_unlock(&mtx3);

		write(STDOUT_FILENO, "D", 1);

		pthread_mutex_lock(&mtx4);
		finished4 = 1;
		pthread_mutex_unlock(&mtx4);

		pthread_cond_signal(&wait_th4);
		sleep(1);
	}
}


int main() {
	int ret;

	pthread_t tid1, tid2, tid3, tid4;
	ret = pthread_create(&tid1, NULL, th1, NULL);
	if (ret != 0) {
		errno = ret;
		perror("creaet th1");
		return 1;
	}	
	ret = pthread_create(&tid2, NULL, th2, NULL);
	if (ret != 0) {
		errno = ret;
		perror("creaet th1");
		return 1;
	}	
	ret = pthread_create(&tid3, NULL, th3, NULL);
	if (ret != 0) {
		errno = ret;
		perror("creaet th1");
		return 1;
	}	
	ret = pthread_create(&tid4, NULL, th4, NULL);
	if (ret != 0) {
		errno = ret;
		perror("creaet th1");
		return 1;
	}	

	pthread_mutex_lock(&mtx4);
	finished4 = 1;
	pthread_mutex_unlock(&mtx4);

	pthread_cond_signal(&wait_th4);

	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	pthread_join(tid3, NULL);
	pthread_join(tid4, NULL);
}
